/*
 * Copyright (c) 2003-2010, Live Media Pty. Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *     conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *  3. Neither the name of Live Media nor the names of its contributors may be used to endorse
 *     or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.colony.transport.udp;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import com.argot.remote.transport.TypeEndPoint;
import com.colony.concurrent.Queue;
import com.colony.concurrent.ThreadActivator;
import com.colony.transport.Client;


public class UdpClient
implements Client
{
	private static int BUFFER_SIZE = 256;
	
	private DatagramSocket _ds;
	private InetAddress _host;
	private int _port;
	private int _maxRetries = 3;
	private int _responseTimeout = 3000;
	
	public UdpClient( ThreadActivator pool, String host, int port ) 
	throws SocketException, UnknownHostException
	{
		_ds = new DatagramSocket(port);
		_host = InetAddress.getByName(host);
		_port = port;
		
		
		//pool.assignThread( new UdpClientThread() );
	}
	

	public void closeLink(TypeEndPoint endPoint)
	{
		// nothing to do here.
	}

	public TypeEndPoint openLink() 
	throws IOException
	{
		return new UdpEndPoint(this);
	}


	public ByteArrayInputStream sendRequest(ByteArrayOutputStream data) 
	throws IOException
	{
		int retryCount = 0;
		
		while (retryCount < _maxRetries)
		{
			byte[] outBuffer = data.toByteArray();

			System.out.println("Sending " + outBuffer.length +":");			
			writeData(outBuffer, outBuffer.length);
			// send the data to the server.
			_ds.send(new DatagramPacket(outBuffer,data.size(),_host,_port));
			
			byte[] buffer = new byte[BUFFER_SIZE];
			DatagramPacket p = new DatagramPacket(buffer,buffer.length);
			
			// wait for a response
			_ds.receive(p);
			System.out.println("Received " + p.getLength() + ":" );
			writeData(buffer, p.getLength());

			ByteArrayInputStream responseData;

			// Hack for RpcClient which doesn't strip the first byte of the response.
			if (buffer[0] == 7 )
			{
				responseData = new ByteArrayInputStream(buffer,1,p.getLength());		
			}
			else
			{
				responseData = new ByteArrayInputStream(buffer,0,p.getLength());
			}
			
			
			return responseData;
			//retryCount++;
		}
		
		return null;
	}
	
	
	private void writeData(byte[] core,int length)
	{
	      int count=0;
	        for (int x=0; x<length;x++)
	        {
	        	count++;
	        	
	        	if (core[x] >= 65 && core[x] <= 122 )
	        	{
	        		String value = String.valueOf((char)core[x]);
	        		System.out.print( value + "  ");
	        	}
	        	else
	        	{
		        	String value = Integer.toString( core[x], 16 );
		        	if (value.length()==1) value = "0" + value;
		        	value = "" + value;
		        	
		        	System.out.print( "" + value + " ");
	        	}
	        	if (count>30)
	        	{
	        		count=0;
	        		System.out.println("");
	        	}
	        }
	        System.out.println();
		
	}
	
	private class UdpClientThread
	implements Runnable
	{

		public void run()
		{
			while(true) 
			{
				
				byte[] buffer = new byte[BUFFER_SIZE];
				DatagramPacket p = new DatagramPacket(buffer,buffer.length);
				
				try
				{
					_ds.receive(p);
					System.out.println("got UDP data - " + p.getLength() );
					ByteArrayInputStream responseData = new ByteArrayInputStream(buffer,0,p.getLength());
					
					// put response data on queue.
					//_queue.write(responseData);
				} 
				catch (IOException e)
				{
					e.printStackTrace();
				}
			} 
		}
		
	}

	

}
